﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.SessionState;
using Newtonsoft.Json;
using System.Reflection;
using Model;
using BLL;
using System.Data.Entity;
using WebApplication.AppCode;
using WebApplication.AppCode.View;
using System.Linq.Expressions;
using Newtonsoft.Json.Linq;

namespace WebApplication
{
    /// <summary>
    /// Handler 的摘要说明
    /// </summary>
    public class Handler : IHttpHandler, IRequiresSessionState
    {
        object locker = new object();
        static Dictionary<string, MethodInfo> methodDict = new Dictionary<string, MethodInfo>();
        SysBLL bll = new SysBLL();
        AppBLL appBLL = new AppBLL();

        HttpContext context = null;

        public void ProcessRequest(HttpContext context)
        {
            this.context = context;
            context.Response.ContentType = "text/json";
            if (!Helper.AllowAccess())
            {
                WriteResultJson(false, "拒绝访问！"); return;
            }

            String methodName = context.Request["method"];
            if (string.IsNullOrEmpty(methodName)) { return; }
            Type type = this.GetType();
            MethodInfo method = null;
            if (!methodDict.ContainsKey(methodName))
            {
                lock (locker)
                {
                    if (!methodDict.ContainsKey(methodName))
                    {
                        method = type.GetMethod(methodName);
                        methodDict.Add(methodName, method);
                    }
                }
            }

            method = methodDict[methodName];
            if (method == null)
            {
                WriteResultJson(false, "没有找到方法：" + methodName); return;
            }

            try
            {
                method.Invoke(this, null);
            }
            catch (Exception ex)
            {
                WriteResultJson(false, ex.Message); ;
            }
            finally
            {

            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

        #region 联系人
        public void LoadContacts()
        {
            int pageIndex = 0;
            int pageSize = 20;
            string sortField = "";
            string sortOrder = "";
            int.TryParse(context.Request["pageIndex"], out pageIndex);
            int.TryParse(context.Request["pageSize"], out pageSize);
            if (pageIndex < 0) { pageIndex = 0; }
            if (pageSize <= 0) { pageSize = 20; }
            sortField = context.Request["sortField"];
            sortOrder = context.Request["sortOrder"];
            if (string.IsNullOrEmpty(sortField)) { sortField = "Name"; }
            if (string.IsNullOrEmpty(sortOrder)) { sortOrder = "asc"; }


            string key = context.Request["key"];
            List<Expression<Func<Contacts, bool>>> conditions = new List<Expression<Func<Contacts, bool>>>();
            if (!string.IsNullOrEmpty(key))
            {
                conditions.Add(x => x.Name.Contains(key) || x.RelatedParty.Contains(key) || x.Title.Contains(key) || x.PhoneNumber.Contains(key));
            }
            Expression<Func<Contacts, string>> orderFunc = null;
            switch (sortField.ToLower())
            {
                case "phonenumber":
                    orderFunc = x => x.PhoneNumber;
                    break;
                case "relatedparty":
                    orderFunc = x => x.RelatedParty;
                    break;
                case "title":
                    orderFunc = x => x.Title;
                    break;
                default:
                    orderFunc = x => x.Name;
                    break;
            }

            int total = 0;
            List<Contacts> users = null;
            if (sortOrder.ToLower() == "asc")
            {
                users = appBLL.DbContext.GetPagedEntities<Contacts, string>(pageIndex, pageSize, out total, orderFunc, true, conditions.ToArray()).ToList();
            }
            else
            {
                users = appBLL.DbContext.GetPagedEntities<Contacts, string>(pageIndex, pageSize, out total, orderFunc, false, conditions.ToArray()).ToList();
            }

            WriteResultJson(new { total = total, data = users });
        }

        public void SaveContacts()
        {
            var datas = JsonConvert.DeserializeObject<List<ContactsView>>(HttpContext.Current.Request["data"]);

            if (datas == null || datas.Count == 0)
            {
                WriteSubmitInvalidaDataJson(); return;
            }

            List<int> exists = new List<int>();
            List<ContactsView> deleteList = new List<ContactsView>();
            List<ContactsView> addList = new List<ContactsView>();
            List<ContactsView> updateList = new List<ContactsView>();

            for (int i = 0; i < datas.Count; i++)
            {
                switch (datas[i]._state)
                {
                    case "removed":
                        deleteList.Add(datas[i]);
                        break;
                    case "added":
                        addList.Add(datas[i]);
                        break;
                    case "modified":
                        updateList.Add(datas[i]);
                        break;
                }
            }

            if (deleteList.Count > 0)
            {
                deleteList.ForEach(x =>
                {
                    appBLL.DbContext.Delete(x.GetContacts());
                });
            }

            addList.ForEach(x =>
            {
                x.ID = Guid.NewGuid();
                appBLL.DbContext.Contacts.Add(x.GetContacts());
            });
            updateList.ForEach(x =>
            {
                var role = x.GetContacts();
                appBLL.DbContext.Contacts.Attach(role);
                appBLL.DbContext.Entry(role).State = EntityState.Modified;
            });

            try
            {
                appBLL.DbContext.SaveChanges();
                WriteResultJson(true);
            }
            catch (Exception ex)
            {
                WriteExceptionJson(ex);
            }
        }
        #endregion

        #region 环节
        public void LoadNode()
        {
            int pageIndex = 0;
            int pageSize = 20;
            string sortField = "";
            string sortOrder = "";
            int.TryParse(context.Request["pageIndex"], out pageIndex);
            int.TryParse(context.Request["pageSize"], out pageSize);
            if (pageIndex < 0) { pageIndex = 0; }
            if (pageSize <= 0) { pageSize = 20; }
            sortField = context.Request["sortField"];
            sortOrder = context.Request["sortOrder"];
            if (string.IsNullOrEmpty(sortField)) { sortField = "Content"; }
            if (string.IsNullOrEmpty(sortOrder)) { sortOrder = "asc"; }


            string key = context.Request["key"];
            List<Expression<Func<ProjectNode, bool>>> conditions = new List<Expression<Func<ProjectNode, bool>>>();
            if (!string.IsNullOrEmpty(key))
            {
                conditions.Add(x => x.Content.Contains(key));
            }

            int total = 0;
            List<ProjectNode> users = null;
            bool asc = sortOrder.ToLower() == "asc";

            switch (sortField.ToLower())
            {
                case "days":
                    users = appBLL.DbContext.GetPagedEntities<ProjectNode, int>(pageIndex, pageSize, out total, x => x.StandardDays, asc, conditions.ToArray()).ToList();
                    break;
                default:
                    users = appBLL.DbContext.GetPagedEntities<ProjectNode, string>(pageIndex, pageSize, out total, x => x.Content, asc, conditions.ToArray()).ToList();
                    break;
            }
            WriteResultJson(new { total = total, data = users });
        }

        public void SaveNode()
        {

        }

        #endregion

        #region 环节流程
        public void LoadPoint()
        {
            int pageIndex = 0;
            int pageSize = 20;
            string sortField = "";
            string sortOrder = "";
            int.TryParse(context.Request["pageIndex"], out pageIndex);
            int.TryParse(context.Request["pageSize"], out pageSize);
            if (pageIndex < 0) { pageIndex = 0; }
            if (pageSize <= 0) { pageSize = 20; }
            sortField = context.Request["sortField"];
            sortOrder = context.Request["sortOrder"];
            if (string.IsNullOrEmpty(sortField)) { sortField = "Name"; }
            if (string.IsNullOrEmpty(sortOrder)) { sortOrder = "asc"; }


            string key = context.Request["key"];
            List<Expression<Func<Point, bool>>> conditions = new List<Expression<Func<Point, bool>>>();
            if (!string.IsNullOrEmpty(key))
            {
                conditions.Add(x => x.Name.Contains(key));
            }

            int total = 0;
            List<Point> users = null;
            bool asc = sortOrder.ToLower() == "asc";

            switch (sortField.ToLower())
            {
                case "id":
                    users = appBLL.DbContext.GetPagedEntities<Point, Guid>(pageIndex, pageSize, out total, x => x.ID, asc, conditions.ToArray()).ToList();
                    break;
                default:
                    users = appBLL.DbContext.GetPagedEntities<Point, string>(pageIndex, pageSize, out total, x => x.Name, asc, conditions.ToArray()).ToList();
                    break;
            }
            WriteResultJson(new { total = total, data = users });
        }

        public void SavePoint()
        {
            var datas = JsonConvert.DeserializeObject<List<Point>>(HttpContext.Current.Request["data"]);
            var views = JsonConvert.DeserializeObject<List<ModelView>>(HttpContext.Current.Request["data"]);

            if (datas == null || datas.Count == 0)
            {
                WriteSubmitInvalidaDataJson(); return;
            }

            List<Point> deleteList = new List<Point>();
            List<Point> addList = new List<Point>();
            List<Point> updateList = new List<Point>();

            for (int i = 0; i < views.Count; i++)
            {
                switch (views[i]._state)
                {
                    case "removed":
                        deleteList.Add(datas[i]);
                        break;
                    case "added":
                        addList.Add(datas[i]);
                        break;
                    case "modified":
                        updateList.Add(datas[i]);
                        break;
                }
            }

            if (deleteList.Count > 0)
            {
                deleteList.ForEach(x =>
                {
                    appBLL.DbContext.Delete(x);
                });
            }

            addList.ForEach(x =>
            {
                x.ID = Guid.NewGuid();
                appBLL.DbContext.Points.Add(x);
            });
            updateList.ForEach(x =>
            {
                appBLL.DbContext.Points.Attach(x);
                appBLL.DbContext.Entry(x).State = EntityState.Modified;
            });

            try
            {
                appBLL.DbContext.SaveChanges();
                WriteResultJson(true);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null && ex.InnerException.InnerException != null && ex.InnerException.InnerException.Message.Contains("DELETE 语句与 REFERENCE 约束"))
                {
                    WriteResultJson(false, "无法删除已被使用的数据！");
                }
                else
                {
                    WriteExceptionJson(ex);
                }
            }
        }

        public void LoadProjectNodePoint()
        {
            Guid id;
            if (!Guid.TryParse(context.Request["ProjectNodeID"], out id))
            {
                WriteResultJson(new { total = 0 });
                WriteSubmitInvalidaDataJson(); return;
            }

            try
            {
                var items = from s in appBLL.DbContext.ProjectNodePoints.Where(x => x.ProjectNodeID == id)
                            select new { s.ID, s.ProjectNodeID, s.PointID, s.PointItem.Name };
                WriteResultJson(new { total = items.Count(), data = items });
            }
            catch (Exception ex)
            {
                WriteExceptionJson(ex);
            }
        }
        #endregion

        #region 区域
        public void LoadArea()
        {
            int pageIndex = 0;
            int pageSize = 20;
            string sortField = "";
            string sortOrder = "";
            int.TryParse(context.Request["pageIndex"], out pageIndex);
            int.TryParse(context.Request["pageSize"], out pageSize);
            if (pageIndex < 0) { pageIndex = 0; }
            if (pageSize <= 0) { pageSize = 20; }
            sortField = context.Request["sortField"];
            sortOrder = context.Request["sortOrder"];
            if (string.IsNullOrEmpty(sortField)) { sortField = "Name"; }
            if (string.IsNullOrEmpty(sortOrder)) { sortOrder = "asc"; }


            string key = context.Request["key"];
            List<Expression<Func<Department, bool>>> conditions = new List<Expression<Func<Department, bool>>>();
            if (!string.IsNullOrEmpty(key))
            {
                conditions.Add(x => x.Name.Contains(key));
            }

            int total = 0;
            List<Department> users = null;
            if (sortOrder.ToLower() == "asc")
            {
                users = appBLL.DbContext.GetPagedEntities<Department, string>(pageIndex, pageSize, out total, x => x.Name, true, conditions.ToArray()).ToList();
            }
            else
            {
                users = appBLL.DbContext.GetPagedEntities<Department, string>(pageIndex, pageSize, out total, x => x.Name, false, conditions.ToArray()).ToList();
            }

            WriteResultJson(new { total = total, data = users });
        }

        public void SaveArea()
        {
            var datas = JsonConvert.DeserializeObject<List<Department>>(HttpContext.Current.Request["data"]);
            var views = JsonConvert.DeserializeObject<List<ModelView>>(HttpContext.Current.Request["data"]);

            if (datas == null || datas.Count == 0)
            {
                WriteSubmitInvalidaDataJson(); return;
            }

            for (int i = 0; i < views.Count; i++)
            {
                switch (views[i]._state)
                {
                    case "removed":
                        appBLL.DbContext.Delete(datas[i]);
                        break;
                    case "added":
                        datas[i].ID = Guid.NewGuid();
                        appBLL.DbContext.Departments.Add(datas[i]);
                        break;
                    case "modified":
                        appBLL.DbContext.Departments.Attach(datas[i]);
                        appBLL.DbContext.Entry(datas[i]).State = EntityState.Modified;
                        break;
                }
            }

            try
            {
                appBLL.DbContext.SaveChanges();
                WriteResultJson(true);
            }
            catch (Exception ex)
            {
                WriteExceptionJson(ex);
            }
        }
        #endregion

        #region 项目
        public void LoadProject()
        {
            int pageIndex = 0;
            int pageSize = 20;
            string sortField = "";
            string sortOrder = "";
            int.TryParse(context.Request["pageIndex"], out pageIndex);
            int.TryParse(context.Request["pageSize"], out pageSize);
            if (pageIndex < 0) { pageIndex = 0; }
            if (pageSize <= 0) { pageSize = 20; }
            sortField = context.Request["sortField"];
            sortOrder = context.Request["sortOrder"];
            if (string.IsNullOrEmpty(sortField)) { sortField = "Name"; }
            if (string.IsNullOrEmpty(sortOrder)) { sortOrder = "asc"; }


            string key = context.Request["key"];
            List<Expression<Func<Project, bool>>> conditions = new List<Expression<Func<Project, bool>>>();
            if (!string.IsNullOrEmpty(key))
            {
                conditions.Add(x => x.Name.Contains(key));
            }

            int total = 0;
            List<Project> projects = null;
            bool asc = sortOrder.ToLower() == "asc";
            switch (sortField.ToLower())
            {
                case "begindate":
                    projects = appBLL.DbContext.GetPagedEntities<Project, DateTime>(pageIndex, pageSize, out total, x => x.BeginDate.Value, asc, conditions.ToArray()).ToList();
                    break;
                case "enddate":
                    projects = appBLL.DbContext.GetPagedEntities<Project, DateTime>(pageIndex, pageSize, out total, x => x.EndDate.Value, asc, conditions.ToArray()).ToList();
                    break;
                case "description":
                    projects = appBLL.DbContext.GetPagedEntities<Project, string>(pageIndex, pageSize, out total, x => x.Description, asc, conditions.ToArray()).ToList();
                    break;
                default:
                    projects = appBLL.DbContext.GetPagedEntities<Project, string>(pageIndex, pageSize, out total, x => x.Name, asc, conditions.ToArray()).ToList();
                    break;
            }
            List<object> items = new List<object>();
            projects.ForEach(x =>
            {
                items.Add(new
                {
                    ID = x.ID,
                    Name = x.Name,
                    Description = x.Description,
                    BeginDate = x.BeginDate,
                    EndDate = x.EndDate,
                    IsStart = x.BeginDate.HasValue && DateTime.Compare(x.BeginDate.Value, DateTime.Now) < 0
                });
            });
            WriteResultJson(new { total = total, data = items });
        }

        public void SaveProject()
        {
            var datas = JsonConvert.DeserializeObject<List<Project>>(HttpContext.Current.Request["data"]);
            var views = JsonConvert.DeserializeObject<List<ModelView>>(HttpContext.Current.Request["data"]);

            if (datas == null || datas.Count == 0)
            {
                WriteSubmitInvalidaDataJson(); return;
            }

            for (int i = 0; i < views.Count; i++)
            {
                switch (views[i]._state)
                {
                    case "removed":
                        appBLL.Delete(datas[i]);
                        break;
                    case "added":
                        datas[i].ID = Guid.NewGuid();
                        appBLL.DbContext.Projects.Add(datas[i]);
                        break;
                    case "modified":
                        appBLL.DbContext.Projects.Attach(datas[i]);
                        appBLL.DbContext.Entry(datas[i]).State = EntityState.Modified;
                        break;
                }
            }

            try
            {
                appBLL.DbContext.SaveChanges();
                WriteResultJson(true);
            }
            catch (Exception ex)
            {
                WriteExceptionJson(ex);
            }
        }

        public void SaveProjectData()
        {
            var data = JsonConvert.DeserializeObject<Model.ProjectView>(HttpContext.Current.Request["data"]);
            JObject json = (JObject)JsonConvert.DeserializeObject(HttpContext.Current.Request["data"]);

            if (data == null)
            {
                WriteSubmitInvalidaDataJson(); return;
            }

            if (data.Project.ID == Guid.Empty)
            {
                data.Project.ID = Guid.NewGuid();
                appBLL.DbContext.Projects.Add(data.Project);
            }
            else
            {
                appBLL.DbContext.Projects.Attach(data.Project);
                appBLL.DbContext.Entry(data.Project).State = EntityState.Modified;
            }

            for (int i = 0; i < data.Areas.Count; i++)
            {
                switch (json["Areas"][i]["_state"].ToString())
                {
                    case "removed":
                        appBLL.DbContext.Delete(data.Areas[i]);

                        break;
                    case "added":
                        data.Areas[i].ID = Guid.NewGuid();
                        data.Areas[i].ProjectID = data.Project.ID;
                        appBLL.DbContext.ProjectAreas.Add(data.Areas[i]);
                        break;
                    case "modified":
                        appBLL.DbContext.ProjectAreas.Attach(data.Areas[i]);
                        appBLL.DbContext.Entry(data.Areas[i]).State = EntityState.Modified;
                        break;
                }
            }

            for (int i = 0; i < data.Nodes.Count; i++)
            {
                switch (json["Nodes"][i]["_state"].ToString())
                {
                    case "removed":
                        appBLL.DbContext.Delete(data.Nodes[i]);
                        appBLL.DeleteRelationshipByNodeID(data.Nodes[i].ID);
                        break;
                    case "added":
                        //data.Nodes[i].ID = Guid.NewGuid();
                        data.Nodes[i].ProjectID = data.Project.ID;
                        data.Nodes[i].Status = NodeStatusEnum.Waiting;
                        appBLL.DbContext.ProjectNodes.Add(data.Nodes[i]);
                        if (json["Nodes"][i]["NextNodes"] != null)
                        {
                            var NextNodes = json["Nodes"][i]["NextNodes"].ToString().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                            NextNodes.ForEach(x =>
                            {
                                appBLL.DbContext.NodeRelationships.Add(new NodeRelationship { NodeID = data.Nodes[i].ID, NextNodeID = Guid.Parse(x) });
                            });
                        }
                        break;
                    case "modified":
                        appBLL.DbContext.ProjectNodes.Attach(data.Nodes[i]);
                        appBLL.DbContext.Entry(data.Nodes[i]).State = EntityState.Modified;
                        appBLL.DeleteRelationshipByNodeID(data.Nodes[i].ID);
                        if (json["Nodes"][i]["NextNodes"] != null)
                        {
                            var NextNodes0 = json["Nodes"][i]["NextNodes"].ToString().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                            NextNodes0.ForEach(x =>
                            {
                                appBLL.DbContext.NodeRelationships.Add(new NodeRelationship { NodeID = data.Nodes[i].ID, NextNodeID = Guid.Parse(x) });
                            });
                        }
                        break;
                }
            }

            try
            {
                appBLL.DbContext.SaveChanges();
                WriteJson(new { Success = true, ID = data.Project.ID.ToString() });
            }
            catch (Exception ex)
            {
                WriteExceptionJson(ex);
            }
        }

        #endregion

        #region 系统管理
        #region 菜单
        public void SaveMenu()
        {
            var item = JsonConvert.DeserializeObject<SysMenu>(HttpContext.Current.Request["data"]);
            if (item == null)
            {
                WriteSubmitInvalidaDataJson(); return;
            }
            if (item.ID == Guid.Empty)
            {
                item.ID = Guid.NewGuid();
                bll.DbContext.Menus.Add(item);
            }
            else
            {
                item = bll.DbContext.Menus.Attach(item);
                bll.DbContext.Entry(item).State = EntityState.Modified;
            }
            try
            {
                bll.DbContext.SaveChanges();
                WriteResultJson(true);
            }
            catch (Exception ex)
            {
                WriteExceptionJson(ex);
            }
        }

        public void LoadMenu()
        {
            bool show = HttpContext.Current.Request["mode"] == "default";
            List<object> menus = new List<object>();
            if (show)
            {
                var items = bll.DbContext.Menus.Where(w => w.Visible).OrderBy(x => x.Order).ToList();
                items.ForEach(x =>
                {
                    menus.Add(new { id = x.ID, pid = x.PID, text = x.Text, iconCls = x.IconClassName, url = x.Url, Visible = x.Visible });
                });
            }
            else
            {
                var items = bll.DbContext.Menus.OrderBy(x => x.Order).ToList();
                items.ForEach(x =>
                {
                    menus.Add(new { ID = x.ID, PID = x.PID, Text = x.Text, iconCls = x.IconClassName, Url = x.Url, Visible = x.Visible });
                });
            }

            WriteResultJson(menus);
        }

        public void DelMenu()
        {
            List<Guid> ids = JsonConvert.DeserializeObject<List<Guid>>(HttpContext.Current.Request["data"]);
            if (ids == null || ids.Count == 0)
            {
                WriteSubmitInvalidaDataJson(); return;
            }
            var menus = bll.DbContext.Menus.Where(x => ids.Contains(x.ID)).ToList();
            menus.ForEach(x =>
            {
                bll.DbContext.Delete(x);
            });
            try
            {
                bll.DbContext.SaveChanges();
                WriteResultJson(true);
            }
            catch (Exception ex)
            {
                WriteExceptionJson(ex);
            }
        }
        #endregion

        #region 角色
        public void LoadRole()
        {
            List<SysRole> roles = null;
            try
            {
                roles = bll.DbContext.Roles.OrderBy(x => x.Name).ToList();
            }
            catch (Exception ex)
            {
                WriteExceptionJson(ex); return;
            }
            if (context.Request["mode"] == "tree")
            {
                List<object> items = new List<object>();
                var root = new { ID = Guid.NewGuid(), PID = Guid.Empty, Name = "所有角色", Description = "" };
                items.Add(root);
                roles.ForEach(x =>
                {
                    items.Add(new { ID = x.ID, PID = root.ID, Name = x.Name, Description = x.Description });
                });
                WriteResultJson(items);
            }
            else
            {
                WriteResultJson(roles);
            }
        }

        public void SaveRole()
        {
            var datas = JsonConvert.DeserializeObject<List<RoleView>>(HttpContext.Current.Request["data"]);

            if (datas == null || datas.Count == 0)
            {
                WriteSubmitInvalidaDataJson(); return;
            }

            List<int> exists = new List<int>();
            List<RoleView> deleteList = new List<RoleView>();
            List<RoleView> addList = new List<RoleView>();
            List<RoleView> updateList = new List<RoleView>();

            for (int i = 0; i < datas.Count; i++)
            {
                switch (datas[i]._state)
                {
                    case "removed":
                        deleteList.Add(datas[i]);
                        break;
                    case "added":
                        addList.Add(datas[i]);
                        break;
                    case "modified":
                        updateList.Add(datas[i]);
                        break;
                }
            }

            var groups = addList.GroupBy(x => x.Name);
            groups.ToList().ForEach(x =>
            {
                var list = x.ToList();
                if (list.Count > 1)
                {
                    exists.Add(list[0]._uid);
                }
            });

            addList.ForEach(x =>
            {
                int count = bll.DbContext.Roles.Count(c => c.Name == x.Name);
                if (count > 0)
                {
                    exists.Add(x._uid);
                }
            });
            updateList.ForEach(x =>
            {
                int count = bll.DbContext.Roles.Count(c => c.Name == x.Name && c.ID != x.ID);
                count += addList.Count(c => c.Name == x.Name);
                if (count > 0)
                {
                    exists.Add(x._uid);
                }
            });

            if (exists.Count > 0)
            {
                WriteResultJson(new { Success = false, Exists = exists }); return;
            }

            if (deleteList.Count > 0)
            {
                deleteList.ForEach(x =>
                {
                    bll.DbContext.Delete(x.GetRole());
                });
            }

            addList.ForEach(x =>
            {
                x.ID = Guid.NewGuid();
                bll.DbContext.Roles.Add(x.GetRole());
            });
            updateList.ForEach(x =>
            {
                var role = x.GetRole();
                bll.DbContext.Roles.Attach(role);
                bll.DbContext.Entry(role).State = EntityState.Modified;
            });

            try
            {
                bll.DbContext.SaveChanges();
                WriteResultJson(true);
            }
            catch (Exception ex)
            {
                WriteExceptionJson(ex);
            }
        }
        #endregion

        #region 用户
        public void LoadUser()
        {
            int pageIndex = 0;
            int pageSize = 20;
            string sortField = "";
            string sortOrder = "";
            int.TryParse(context.Request["pageIndex"], out pageIndex);
            int.TryParse(context.Request["pageSize"], out pageSize);
            if (pageIndex < 0) { pageIndex = 0; }
            if (pageSize <= 0) { pageSize = 20; }
            sortField = context.Request["sortField"];
            sortOrder = context.Request["sortOrder"];
            if (string.IsNullOrEmpty(sortField)) { sortField = "account"; }
            if (string.IsNullOrEmpty(sortOrder)) { sortOrder = "asc"; }


            string key = context.Request["key"];
            List<Expression<Func<UserInfo, bool>>> conditions = new List<Expression<Func<UserInfo, bool>>>();
            if (!string.IsNullOrEmpty(key))
            {
                conditions.Add(x => x.Account.Contains(key) || x.Name.Contains(key) || x.Department.Contains(key) || x.Title.Contains(key));
            }
            Expression<Func<UserInfo, string>> orderFunc = null;
            switch (sortField.ToLower())
            {
                case "name":
                    orderFunc = x => x.Name;
                    break;
                case "department":
                    orderFunc = x => x.Department;
                    break;
                case "title":
                    orderFunc = x => x.Title;
                    break;
                default:
                    orderFunc = x => x.Account;
                    break;
            }

            int total = 0;
            List<UserInfo> users = null;
            if (sortOrder.ToLower() == "asc")
            {
                users = bll.DbContext.GetPagedEntities<UserInfo, string>(pageIndex, pageSize, out total, orderFunc, true, conditions.ToArray()).ToList();
            }
            else
            {
                users = bll.DbContext.GetPagedEntities<UserInfo, string>(pageIndex, pageSize, out total, orderFunc, false, conditions.ToArray()).ToList();
            }

            WriteResultJson(new { total = total, data = users });
        }
        #endregion

        #region 用户角色
        public void SaveUserRole()
        {
            var data = (JObject)JsonConvert.DeserializeObject(context.Request["data"]);

            Guid roleID;
            if (data["RID"] == null || !Guid.TryParse(data["RID"].ToString(), out roleID))
            {
                WriteSubmitInvalidaDataJson(); return;
            }

            if (data["Accounts"] == null || data["Accounts"].Count() == 0)
            {
                WriteSubmitInvalidaDataJson(); return;
            }
            var datas = data["Accounts"].ToList();
            datas.ForEach(x =>
            {
                SysUserRole role = new SysUserRole { RoleID = roleID, Account = x.ToString(), ID = Guid.NewGuid() };
                bll.DbContext.UserRoles.Add(role);
            });

            try
            {
                bll.DbContext.SaveChanges();
                WriteSuccessJson();
            }
            catch (Exception ex)
            {
                WriteExceptionJson(ex);
            }
        }

        public void GetUserByRoleID()
        {
            int pageIndex = 0;
            int pageSize = 20;
            string sortField = "";
            string sortOrder = "";
            int.TryParse(context.Request["pageIndex"], out pageIndex);
            int.TryParse(context.Request["pageSize"], out pageSize);
            if (pageIndex < 0) { pageIndex = 0; }
            if (pageSize <= 0) { pageSize = 20; }
            sortField = context.Request["sortField"];
            sortOrder = context.Request["sortOrder"];
            if (string.IsNullOrEmpty(sortField)) { sortField = "account"; }
            if (string.IsNullOrEmpty(sortOrder)) { sortOrder = "asc"; }

            //var accounts = from y in bll.DbContext.UserRoles select y.Account;
            //var datas = from x in bll.DbContext.Users where accounts.Contains(x.Account) select x;

            var items = bll.DbContext.Users.Join(bll.DbContext.UserRoles, x => x.Account, x => x.Account,
                (x, y) => new UserRoleView
                {
                    ID = y.ID,
                    RoleID = y.RoleID,
                    RoleName = y.Role.Name,
                    Account = x.Account,
                    Name = x.Name,
                    Department = x.Department,
                    Title = x.Title
                });

            string key = context.Request["key"];
            if (!string.IsNullOrEmpty(key))
            {
                items = items.Where(x => x.Account.Contains(key) || x.Name.Contains(key) || x.Department.Contains(key) || x.Title.Contains(key));
            }
            Guid roleID;
            if (Guid.TryParse(context.Request["RID"], out roleID))
            {
                items = items.Where(x => x.RoleID == roleID);
            }

            Expression<Func<UserRoleView, string>> orderFunc = null;
            switch (sortField.ToLower())
            {
                case "name":
                    orderFunc = x => x.Name;
                    break;
                case "department":
                    orderFunc = x => x.Department;
                    break;
                case "title":
                    orderFunc = x => x.Title;
                    break;
                default:
                    orderFunc = x => x.Account;
                    break;
            }

            int total = items.Count();
            if (sortOrder.ToLower() == "asc")
            {
                items = items.OrderBy(orderFunc);
            }
            else
            {
                items = items.OrderByDescending(orderFunc);
            }

            items = items.Skip(pageIndex * pageSize).Take(pageSize);
            WriteResultJson(new { total = total, data = items });
        }

        public void DelUserRole()
        {
            string ids = context.Request["ids"];
            if (string.IsNullOrEmpty(ids))
            {
                WriteSubmitInvalidaDataJson(); return;
            }

            var idSet = ids.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
            try
            {
                idSet.ForEach(x =>
                {
                    SysUserRole ur = new SysUserRole { ID = Guid.Parse(x) };
                    bll.DbContext.Delete(ur);
                });
            }
            catch (Exception ex)
            {
                WriteSubmitInvalidaDataJson(); return;
            }

            try
            {
                bll.DbContext.SaveChanges();
                WriteSuccessJson();
            }
            catch (Exception ex)
            {
                WriteExceptionJson(ex);
            }
        }
        #endregion

        #region 权限
        public void GetRoleByMenuID()
        {
            int pageIndex = 0;
            int pageSize = 20;
            string sortField = "";
            string sortOrder = "";
            int.TryParse(context.Request["pageIndex"], out pageIndex);
            int.TryParse(context.Request["pageSize"], out pageSize);
            if (pageIndex < 0) { pageIndex = 0; }
            if (pageSize <= 0) { pageSize = 20; }
            sortField = context.Request["sortField"];
            sortOrder = context.Request["sortOrder"];
            if (string.IsNullOrEmpty(sortField)) { sortField = "account"; }
            if (string.IsNullOrEmpty(sortOrder)) { sortOrder = "asc"; }

            var items = bll.DbContext.Permissions.Join(bll.DbContext.Roles, x => x.RoleID, x => x.ID,
                (x, y) => new PermissionView
                {
                    ID = x.ID,
                    RoleID = y.ID,
                    RoleName = y.Name,
                    MenuID = x.MenuID,
                    Allow = x.Allow
                });

            string key = context.Request["key"];
            if (!string.IsNullOrEmpty(key))
            {
                items = items.Where(x => x.RoleName.Contains(key));
            }
            Guid menuID;
            if (Guid.TryParse(context.Request["MenuID"], out menuID))
            {
                items = items.Where(x => x.MenuID == menuID);
            }

            int total = items.Count();
            if (sortOrder.ToLower() == "asc")
            {
                items = items.OrderBy(x => x.RoleName);
            }
            else
            {
                items = items.OrderByDescending(x => x.RoleName);
            }

            items = items.Skip(pageIndex * pageSize).Take(pageSize);
            WriteResultJson(new { total = total, data = items });
        }

        public void SavePermission()
        {
            var data = (JObject)JsonConvert.DeserializeObject(context.Request["data"]);

            Guid menuID;
            if (data["MID"] == null || !Guid.TryParse(data["MID"].ToString(), out menuID))
            {
                WriteSubmitInvalidaDataJson(); return;
            }

            if (data["RID"] == null || data["RID"].Count() == 0)
            {
                WriteSubmitInvalidaDataJson(); return;
            }
            var datas = data["RID"].ToList();
            datas.ForEach(x =>
            {
                SysPermission role = new SysPermission { MenuID = menuID, RoleID = Guid.Parse(x.ToString()), ID = Guid.NewGuid(), Allow = true };
                bll.DbContext.Permissions.Add(role);
            });

            try
            {
                bll.DbContext.SaveChanges();
                WriteSuccessJson();
            }
            catch (Exception ex)
            {
                WriteExceptionJson(ex);
            }
        }

        public void DelPermission()
        {
            string ids = context.Request["ids"];
            if (string.IsNullOrEmpty(ids))
            {
                WriteSubmitInvalidaDataJson(); return;
            }

            var idSet = ids.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
            try
            {
                idSet.ForEach(x =>
                {
                    SysPermission ur = new SysPermission { ID = Guid.Parse(x) };
                    bll.DbContext.Delete(ur);
                });
            }
            catch (Exception ex)
            {
                WriteSubmitInvalidaDataJson(); return;
            }

            try
            {
                bll.DbContext.SaveChanges();
                WriteSuccessJson();
            }
            catch (Exception ex)
            {
                WriteExceptionJson(ex);
            }
        }
        #endregion
        #endregion

        #region write json method
        protected void WriteJson(object result)
        {
            HttpContext.Current.Response.Write(JsonConvert.SerializeObject(result));
        }

        protected void WriteSuccessJson(string message = null)
        {
            HttpContext.Current.Response.Write(JsonConvert.SerializeObject(new { Success = true, Message = message }));
        }

        protected void WriteResultJson(bool success, string message = null)
        {
            if (!success)
            {
            }
            HttpContext.Current.Response.Write(JsonConvert.SerializeObject(new { Success = success, Message = message }));
        }

        protected void WriteSubmitInvalidaDataJson()
        {
            WriteResultJson(false, "提交的数据错误！");
        }

        protected void WriteExceptionJson(Exception ex)
        {
            WriteResultJson(false, "操作时出现错误：<br>" + ex.Message);
        }

        protected void WriteResultJson(object entity)
        {
            context.Response.Write(JsonConvert.SerializeObject(entity));
        }
        #endregion
    }
}